//
// catGL - Cheap Action-game Tool with WebGL.
//
// Copyright 2010, tmasda.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

var catGL = {};

catGL.load_sync = function(url) {
    var xhr = new XMLHttpRequest();
    xhr.open("GET", url, false);
    xhr.send(null);

    return xhr;
}

catGL.init = function(canvas, arg) {
    var default_arg = {
        shader_path                 : "../shader/",
        resource_path               : "../resource/",
        fovy                        :  45.0,
        znear                       :   0.1,
        zfar                        : 100.0,

        clear_color                 : [0.0, 0.0, 0.0,1.0],
        clear_depth                 : 1.0,

        framerate_id                : "",
        framerate_updateInterval    : 500,

        draw_model_axis             : false,
        axis_length                 : 1,
    };

    if (!arg || typeof arg !== "object"){
        arg = default_arg;
    } else {
        if (arg.shader_path){
            if (arg.shader_path.charAt(arg.shader_path.length-1) != "/"){
                arg.shader_path += "/";
            }
        } else {
            arg.shader_path = default_arg.shader_path;
        }
        if (arg.resource_path){
            if (arg.resource_path.charAt(arg.resource_path.length-1) != "/"){
                arg.resource_path += "/";
            }
        } else {
            arg.resource_path = default_arg.resource_path;
        }

        arg.fovy = arg.fovy || default_arg.fovy;
        arg.znear = arg.znear || default_arg.znear;
        arg.aspect = arg.zfar || default_arg.zfar;

        arg.clear_color = arg.clear_color || default_arg.clear_color;
        arg.clear_depth = arg.clear_depth || default_arg.clear_depth;

        arg.framerate_id = arg.framerate_id || default_arg.framerate_id;
        arg.updateInterval = arg.framerate_updateInterval || default_arg.framerate_updateInterval;

        arg.draw_axis = arg.draw_model_axis || default_arg.draw_model_axis;
        arg.length_axis = arg.axis_length || default_arg.axis_length;
    }
    var aspect = canvas.width / canvas.height;
    
    // pathの設定
    this.lib = {};
    this.lib.shaderPath = arg.shader_path;
    this.lib.resourcePath = arg.resource_path;

    // WebGL contextの取得
    try {
        this.gl = canvas.getContext("experimental-webgl");
    } catch (e){
        try {
            this.gl = canvas.getContext("webgl");
        } catch (e2){
            alert(e);
        }
    }
    // WebGL contextの設定
    var gl = catGL.gl;
    var cc = arg.clear_color;
    gl.clearColor(cc[0], cc[1], cc[2], cc[3]);
    gl.clearDepth(arg.clear_depth);

    gl.depthFunc(gl.LEQUAL);
    gl.enable(gl.DEPTH_TEST);
    //gl.disable(gl.BLEND);

    // blendを行う場合の例
    gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
    gl.enable(gl.BLEND);

    // Matrix Stack
    this.matrixStack = MatrixStack.create();

    // Camera
    this.camera = CameraSystem.create();
    this.camera.initialize(canvas.width, canvas.height, arg.fovy, 
                            aspect, arg.znear, arg.zfar);
    
    // Shader Manager
    this.shaderManager = ShaderManager.create();

    // Actor Manager
    this.actorManager = ActorManager.create();
    this.actorManager.draw_model_axis = arg.draw_model_axis;
    if (arg.draw_model_axis){
        this.actorManager.setAxisModel(createAxisModel(arg.axis_length));
    }

    // framerateの表示
    if (arg.framerate_id != ""){
        this.frameRate = FrameRate.create(arg.framerate_id, arg.updateInterval);
    }

    // Key Manager 
    this.keyManager = KeyManager.create();

    // Mouse Manager
    this.mouseManager = MouseManager.create(canvas);

    // Light Manager
    this.lightManager = LightManager.create();
}

catGL.start = function(interval, appLoop)
{

    setInterval(function(){
            // CallBack関数の実行
            if (appLoop){
                appLoop();
            }
            var gl = catGL.gl;
            var camera = catGL.camera;
            var cameraMatrix = catGL.camera.exec();
            var matrixStack = catGL.matrixStack;
            var actorManager = catGL.actorManager;

            // Actor毎の処理の実行
            actorManager.execAllActor();

            // 表示処理
            gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
            var cameraMatrix = camera.exec();
            matrixStack.push(cameraMatrix);
            {
                // ライティングに関する設定のshaderへの設定
                catGL.shaderManager.loadLightParam();

                actorManager.drawAllActor();
                if (actorManager.draw_model_axis){
                    actorManager.drawAllActorAxis();
                }
            }
            matrixStack.pop();
            if (catGL.frameRate){
                catGL.frameRate.record();
            }
        }, interval);
}

//catGL.mainLoop = function()
//{
//    // CallBack関数の実行
//    if (appLoop){
//        appLoop();
//    }
//    // 表示処理
//    var gl = catGL.gl;
//    var camera = catGL.camera;
//    var cameraMatrix = catGL.camera.exec();
//    var matrixStack = catGL.matrixStack;
//    var actorManager = catGL.actorManager;
//    gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
//
//    var cameraMatrix = camera.exec();
//    actorManager.execAllActor();
//
//    matrixStack.push(cameraMatrix);
//    {
//        actorManager.drawAllActor();
//        if (actorManager.draw_model_axis){
//            actorManager.drawAllActorAxis();
//        }
//    }
//    matrixStack.pop();
//    if (catGL.frameRate){
//        catGL.frameRate.record();
//    }
//}
